{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "GEN_3_function_approx.ipynb",
      "provenance": [],
      "authorship_tag": "ABX9TyPhmQE7bYbcMi9rCRbBW+UV",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/cxbxmxcx/GenReality/blob/master/GEN_3_function_approx.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XhB46Q8JTpBd"
      },
      "source": [
        "from sklearn.model_selection import train_test_split\n",
        "\n",
        "import numpy  as np\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "import torch\n",
        "import torch.nn as nn"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9ITk0PPQb67p"
      },
      "source": [
        "def function(X):\n",
        "  return X * X + 5."
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tNHQgiXUUFIa",
        "outputId": "0e61a24f-11ee-4113-d187-728dd1905521",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 439
        }
      },
      "source": [
        "X = np.array([[1.],[2.],[3.],[4.],[5.],[6.],[7.],[8.],[9.],[10.]])\n",
        "y = function(X)\n",
        "inputs = X.shape[1]\n",
        "y = y.reshape(-1, 1)\n",
        "plt.plot(X, y, 'o', color='black')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[ 1.],\n",
              "       [ 2.],\n",
              "       [ 3.],\n",
              "       [ 4.],\n",
              "       [ 5.],\n",
              "       [ 6.],\n",
              "       [ 7.],\n",
              "       [ 8.],\n",
              "       [ 9.],\n",
              "       [10.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 53
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "z05ZyUrmU7is",
        "outputId": "18a806b1-1309-4152-f328-89a5f0da0c1b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)\n",
        "num_train = X_train.shape[0]\n",
        "X_train[:2], y_train[:2]\n",
        "num_train"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "8"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 37
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QLshQolGVUlz"
      },
      "source": [
        "torch.set_default_dtype(torch.float64)\n",
        "net = nn.Sequential(\n",
        "    nn.Linear(inputs, 50, bias = True), nn.ReLU(),\n",
        "    nn.Linear(50, 50, bias = True), nn.ReLU(),\n",
        "    nn.Linear(50, 50, bias = True), nn.Sigmoid(),\n",
        "    nn.Linear(50, 1)\n",
        ")\n",
        "loss_fn = nn.MSELoss()\n",
        "optimizer = torch.optim.Adam(net.parameters(), lr = .001)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ZhR9h8Y3WCWM",
        "outputId": "68d15b86-7efe-4532-df2a-f333087b2dc1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 156
        }
      },
      "source": [
        "num_epochs = 8000\n",
        "y_train_t = torch.from_numpy(y_train).clone().reshape(-1, 1)\n",
        "x_train_t = torch.from_numpy(X_train).clone()\n",
        "y_test_t = torch.from_numpy(y_test).clone().reshape(-1, 1)\n",
        "x_test_t = torch.from_numpy(X_test).clone()\n",
        "history = []"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[ 5.],\n",
              "        [10.],\n",
              "        [ 2.],\n",
              "        [ 7.],\n",
              "        [ 8.],\n",
              "        [ 4.],\n",
              "        [ 1.],\n",
              "        [ 6.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 52
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ef62jrN3WP0d",
        "outputId": "6e3383a2-fafd-4112-d0cb-9c5c23ad3c0b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 347
        }
      },
      "source": [
        "for i in range(num_epochs):\n",
        "    y_pred = net(x_train_t)\n",
        "    loss = loss_fn(y_train_t,y_pred)\n",
        "    history.append(loss.data)    \n",
        "    loss.backward()\n",
        "    optimizer.step()\n",
        "    optimizer.zero_grad()  \n",
        "    test_loss = loss_fn(y_test_t,net(x_test_t))  \n",
        "    if i > 0 and i % 100 == 0:\n",
        "        print(f'Epoch {i}, loss = {loss:.3f}, test loss {test_loss:.3f}')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 100, loss = 2279.083, test loss 3247.548\n",
            "Epoch 200, loss = 2027.327, test loss 2937.767\n",
            "Epoch 300, loss = 1805.935, test loss 2664.226\n",
            "Epoch 400, loss = 1610.167, test loss 2425.456\n",
            "Epoch 500, loss = 1439.706, test loss 2214.201\n",
            "Epoch 600, loss = 1292.612, test loss 2024.813\n",
            "Epoch 700, loss = 1163.477, test loss 1832.955\n",
            "Epoch 800, loss = 1048.232, test loss 1666.764\n",
            "Epoch 900, loss = 946.765, test loss 1515.756\n",
            "Epoch 1000, loss = 856.334, test loss 1377.011\n",
            "Epoch 1100, loss = 775.105, test loss 1249.045\n",
            "Epoch 1200, loss = 702.596, test loss 1131.456\n",
            "Epoch 1300, loss = 638.291, test loss 1023.794\n",
            "Epoch 1400, loss = 581.023, test loss 925.118\n",
            "Epoch 1500, loss = 528.696, test loss 833.552\n",
            "Epoch 1600, loss = 481.186, test loss 748.992\n",
            "Epoch 1700, loss = 438.296, test loss 671.274\n",
            "Epoch 1800, loss = 399.830, test loss 600.118\n",
            "Epoch 1900, loss = 365.543, test loss 535.242\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IifIajH-XFrl",
        "outputId": "f5881699-1d76-4aa2-90c2-dfa902354ff1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 283
        }
      },
      "source": [
        "plt.plot(history)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[<matplotlib.lines.Line2D at 0x7f13d0c47d30>]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 41
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ZJXQixjLhDkt",
        "outputId": "2dcc2150-0596-4eec-bd91-d161ab60dcf3",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 283
        }
      },
      "source": [
        "X_a = torch.rand(25,1).clone() * 9\n",
        "y_a = net(X_a)\n",
        "y_a = y_a.detach().numpy()\n",
        "plt.plot(X_a, y_a, 'o', color='black')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[<matplotlib.lines.Line2D at 0x7f13ced56cc0>]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 67
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    }
  ]
}